(function (window) {
  const PENDING = 'pending';
  const RESOLVED = 'resolved';
  const REJECTED = 'rejected';
  
  // 通过构造函数自定义Promise
  function Promise(executor) {
    
    const self = this;
    self.status = PENDING;
    self.data = undefined;
    self.callbacks = [];
    
    function resolved(value) {
      // 多次调用resolved方法返回
      if (self.status !== PENDING) return
      
      self.status = RESOLVED;
      self.data = value
      if (self.callbacks.length > 0) {
        setTimeout(() => {
          self.callbacks.forEach(cbs => {
            cbs.onResolved(value)
          })
        })
      }
    }
    
    function rejected(reason) {
      // 多次调用rejected方法返回
      if (self.status !== PENDING) return
      
      self.status = REJECTED;
      self.data = reason;
      if (self.callbacks.length > 0) {
        setTimeout(() => {
          self.callbacks.forEach(cbs => {
            cbs.onRejected(reason)
          })
        })
      }
    }
    
    try {
      executor(resolved, rejected)
    } catch (err) {
      rejected(err)
    }
    
  }
  
  // 实例方法then
  Promise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    
    onResolved = typeof onResolved === 'function' ? onResolved : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {
      throw reason
    };
    
    // 返回新的promise
    return new Promise((resolve, reject) => {
      
      // 封装的回调函数
      function handle(callback) {
        try {
          const result = callback(self.data)
          if (result instanceof Promise) {  //返回值是promise
            result.then(value => resolve(value), reason => reject(reason))
          } else {  //返回值不是promise，只是一个普通的值
            resolve(result)
          }
        } catch (err) {  //捕获到错误
          reject(err)
        }
      }
      
      if (this.status === 'resolved') {   //状态为resolved
        setTimeout(() => {
          handle(onResolved)
        })
      } else if (this.status === 'rejected') {   //状态为rejected
        setTimeout(() => {
          handle(onRejected)
        })
      } else {  //状态为pending
        this.callbacks.push({
          onResolved(value) {
            handle(onResolved)
          },
          onRejected(reason) {
            handle(onRejected)
          }
        })
      }
    })
  };
  
  // 实例方法catch
  Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
  }
  
  // 静态方法resolve
  Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
      if (value instanceof Promise) {
        value.then(resolve, reject)
      } else {
        resolve(value)
      }
    })
  }
  
  // 静态方法reject
  Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
      reject(reason)
    })
  }
  
  // 静态方法all
  Promise.all = function (promise) {
    return new Promise((resolve, reject) => {
      let resolvedCount = 0;
      const values = new Array(promise.length)
      promise.forEach((p, index) => {
        p.then(
          value => {
            resolvedCount++;
            values[index] = value
            if (resolvedCount === promise.length) {  //都成功
              resolve(values)
            }
          },
          reason => reject(reason)
        )
      })
    })
  }
  
  // 静态方法race
  Promise.race = function (promise) {
    return new Promise((resolve, reject) => {
      promise.forEach(p => {
        p.then(resolve, reject)
      })
    })
  }
  
  // 自定义具有延时效果静态方法resolveDelay
  Promise.resolveDelay = function (value, time) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (value instanceof Promise) {
          value.then(resolve, reject)
        } else {
          resolve(value)
        }
      },time)
    })
  }

  // 自定义具有延时效果静态方法rejectDelay
  Promise.rejectDelay = function (reason, time) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        reject(reason)
      }, time)
    })
  }
  
  // 将自定义promise挂载到window上
  window.Promise = Promise
})(window)
